home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
LIBRARY
/
PAS_0793
/
CDROM.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-08-01
|
16KB
|
521 lines
{─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
Msg : 317 of 373
From : Marc Van Leeuwen 2:285/228.0 25 Jun 93 12:09
To : Glen Washburn 3:640/305.0
Subj : Using CD-ROM Audio
────────────────────────────────────────────────────────────────────────────────
> I have an NEC CD-ROM and SB Pro package. It came with
> a program called CDPLYR that allows the user to play
> Audio CDs however it is very gludgy only plays the CDs
> in sequential order. Can I control this in PASCAL .
> I want to be able to play different tracks in any
> order. If I hade the interupts or what ever maybe I
> could figure it out for myself
I read this msg here a couple of months ago.
===========================================================}
{(4319) Fri 12 Feb 93 20:25
By: Norbert Igl
To: Pieter Lambrecht
Re: (1) CD-Audio with TP
St:
------------------------------------------------------------
hmmm, Sorry for the german remarks....(:-)
Part - 1 -
}
{$IFDEF DoNotCompileThis}
Unit CDROM;
{ Unit talking to a CD-Rom-Drive
Low-level CD access,
only the first drive is supported...!
Copyright 1992 Norbert Igl }
INTERFACE
TYPE
CD_RECORD = Record
Status : Word; { Status des Drives/letzte Funktion }
DrvChar: Char; { LW-Buchstabe }
DrvNo : Byte; { als Byte ablegegt (0...) }
HSG_RB : byte; { Adressierungs-Modus }
Sector : LongInt; { Adresse des Lesekopfes }
VolInfo: Array[1..8] of Byte; { Lautst.-Einstellungen }
DevPar : LongInt; { Device-parameter, BIT-Feld! }
RawMode: Boolean; { Raw/Cooked-Mode ? }
SecSize: Word; { bytes/Sector }
VolSize: LongInt; { sek/Volume => Groesse der CD}
MedChg : Byte; { Disk gewechselt? }
LoAuTr : Byte; { kleinste Audio-Track # }
HiAuTr : byte; { groesste Audio-Track # }
EndAdr : LongInt; { Adresse der Auslaufrille (8-) }
TrkNo : Byte; { Track #. Eingabe-Wert ! }
TrkAdr : LongInt; { Adresse dieses Tracks }
TrkInf : byte; { Info dazu: BIT-Feld! }
CntAdr : byte; { CONTROL und ADR, von LW }
CTrk : byte; { track # }
Cindx : byte; { point/index }
CMin : byte; { minute\ }
CSek : byte; { second > Laufzeit im Track }
CFrm : byte; { frame / }
Czero : byte; { immer =0 }
CAmin : byte; { minute \ }
CAsec : byte; { sekunde > Laufzeit auf Disk }
CAFrm : byte; { frame / }
Qfrm : LongInt;{ start-frame address }
Qtrfs : LongInt;{ Bufferaddresse }
Qcnt : LongInt;{ Anzahl der Sectoren }
{ pro Sector werden 96 byte nach buffer kopiert }
Uctrl : byte; { CONTROL und ADR byte }
Upn : Array[1..7] of Byte; { EAN-CODE }
Uzero : byte; { immer = 0 }
Ufrm : byte; { Frame-# }
End;
OneTrack = Record
Title : String[20];
Runmin,
RunSec : Byte;
Start : LongInt; { HSG Format ! }
end;
VolumeTableOfContens = Record
Diskname: String[20];
UAN_Code: String[13];
TrackCnt: Byte;
Titles : Array[1..99] of OneTrack;
end;
TrkInfo = Record
Nummer : Byte;
Start : LongInt;
Cntrl2 : Byte;
end;
{===== global verfuegbare Variablen =============}
VAR CD : CD_RECORD;
CD_AVAIL : Boolean;
VTOC : VolumeTableOfContens;
CD_REDPos : String;
CD_HSGPos : String;
{===== allgemeine Funktionen ===================}
Function CD_Reset : Boolean;
Function CD_HeadAdr : Boolean;
Function CD_Position: Boolean;
Function CD_MediaChanged: Boolean;
{===== Tray/Caddy-Funktionen ===================}
Function CD_Open: Boolean;
Function CD_Close: Boolean;
Function CD_Eject: Boolean;
{==== Audio-Funktionen =========================}
Function CD_Play(no:byte; len:integer): Boolean;
Function CD_Stop: Boolean;
Function CD_Resume:Boolean;
Function CD_SetVol:Boolean;
Function CD_GetVol:Boolean;
Procedure CD_Info;
Procedure CD_TrackInfo( Nr:byte; VAR T:TrkInfo );
{==== Umwandlungen =============================}
function Red2Time( Var Inf:TrkInfo ):Word;
IMPLEMENTATION uses Dos;
Type IOCtlBlk = Array[0..200] of Byte;
Const IOCtlRead = $4402;
IOCtlWrite = $4403;
DevDrvReq = $1510;
All:LongInt= $0f00;
Var R : Registers;
H : Text;
Handle : Word;
Old_Exit : Pointer;
CtlBlk : IOCtlBlk;
Tracks : Array[1..100] of TrkInfo;
Procedure CD_Exit; { wird bei Programmende ausgefuehrt }
begin
if Old_Exit <> NIL
then ExitProc := Old_Exit; { Umleitung wieder zuruecknehmen }
{$I-}
Close(H);
If IoResult = 0 then; { 'H' schliessen, falls offen, }
{$I+} { evtl. Fehler verwerfen }
end;
Function CD_Init: Boolean; { Initialisierung beim Programmstart }
begin
FillChar( CD, Sizeof( CD ), 0);
with R do
begin
AX := $1500;
BX := $0000;
CX := $0000;
Intr( $2F, R );
CD_Init := (BX > 0); { Anzahl der CD-Laufwerke }
If BX > 0
then begin
CD.DrvChar { CD-Laufwerksbuchstabe }
:= CHAR( CL + Byte('A') );
CD.DrvNo := CL;
If CD_HeadAdr then
If CD_GetVol then;
end
else CD.DrvChar := '?'; { im Fehlerfall...}
end
end;
Procedure CD_TrackInfo( Nr:byte; VAR T:TrkInfo );
begin
T := Tracks[nr]
end;
Function OpenCDHandle:Word;
Const Name : String[8] = 'MSCD001'; { evt. anpassen!!! ? }
begin
Assign(H, Name); { Filehandle holen }
(*$I-*)
Reset(H);
(*$I+*)
if IoResult = 0 then
begin
Handle := TextRec(H).Handle; { Filehandle holen }
Old_Exit := ExitProc; { Bei Ende/Abbruch muss 'H'... }
ExitProc := @CD_Exit; { ...automatisch geschlossen werden }
end
else Handle := 0;
OpenCDHandle := Handle;
end;
Procedure CloseCDHandle;
begin
if TextRec(H).Mode <> FmClosed
then ExitProc := Old_Exit; { Umleitung wieder zuruecknehmen }
Old_Exit := NIL;
{$I-}
Close(H);
If IoResult = 0 then; { 'H' schliessen, falls offen, }
{$I+} { evtl. Fehler verwerfen }
end;
function Red2HSG( Var Inf:TrkInfo ):LongInt;
var l: longint;
begin
l := LongInt(( Inf.Start shr 16 ) and $FF ) * 4500;
l := l + LongInt(( Inf.Start shr 8 ) and $FF ) * 75;
l := l + LongInt(( Inf.Start ) and $FF ) ;
Red2HSG := l -2;
end;
function Red2Time( Var Inf:TrkInfo ):Word;
begin
Red2Time:= (( Inf.Start shr 24 ) and $FF ) shl 8
+ (( Inf.Start shr 16 ) and $FF )
end;
function HSG2Red(L:Longint):Longint;
begin
end;
Function CD_IOCtl( Func, Len : Word) : Boolean;
begin
With R do
begin
AX := Func;
BX := OpenCDHandle;
CX := 129;
DS := DSeg;
ES := DS;
DX := Ofs(CtlBlk);
MsDos( R );
CD.Status := AX;
CD_IOCtl := (Flags and FCARRY) = 0;
CloseCDHandle;
end
end;
Function CD_Reset: Boolean;
begin
CtlBlk[0] := 2; { reset }
CD_Reset := CD_IoCtl( IoCtlWrite, 1)
end;
Function DieTuer( AufZu:Byte ): Boolean;
begin
CtlBlk[0] := 1; { die Tuer.. }
CtlBlk[1] := AufZu; { ..freigeben }
DieTuer := CD_IoCTL(IoCtlWrite, 2);
end;
Function CD_Open: Boolean;
Const Auf = 0;
begin
CD_Open := DieTuer( Auf );
end;
Function CD_Close: Boolean;
Const Zu = 1;
begin
CD_Close := DieTuer( Zu );
end;
Function CD_Eject: Boolean;
begin
CtlBlk[0] := 0; { CD auswerfen }
CD_Eject := CD_IOCtl(IoCtlWrite, 1);
end;
Function CD_Play(no:byte; len:integer): Boolean;
begin { CD PlayAudio }
FillChar(CtlBlk, sizeof(CtlBlk), 0);
CtlBlk[0] := 22; { laenge des req-hdr }
CtlBlk[1] := 0; { sub-unit }
CtlBlk[2] := $84; { Kommando }
CtlBlk[3] := 0; { Status-WORT }
CtlBlk[4] := 0;
CtlBlk[5] := 0;
CtlBlk[13]:= CD.HSG_RB; { HSG-Modus }
CD.Sector := VTOC.Titles[no].Start; { ist im HSG-Format }
Move( CD.Sector, CtlBlk[14], 4 ); { Start-Sector }
if len = -1
then All := $FFFF
else All := len;
Move( All , CtlBlk[18], 4 ); { Anzahl Sectoren}
ASM
mov ax, $1510
push ds
pop es
xor cx, cx
mov cl, CD.DrvNo
mov bx, offset CtlBlk
Int $2f
end;
CD.Status := CtlBlk[3] or CtlBlk[4] shl 8;
CD_Play := CD.Status and $8000 = 0;
end;
function CD_VTOC:Boolean;
Var i: byte;
l: longint;
begin
FillChar( Tracks, Sizeof( Tracks ), 0);
CtlBlk[0] := 10; { Read LeadOut-Tr }
CD_IoCtl( IoCtlRead, 6);
move( CtlBlk[1], CD.LoAuTr, 6);
i := CD.HiAuTr+1;
move( CtlBlk[3], Tracks[i], 4); { die Auslaufrille 8-) }
Tracks[i].Start := Red2Hsg(Tracks[i]);
for i := CD.LoAuTr to CD.HiAuTr do
begin
FillChar(CtlBlk, sizeof(CtlBlk), 0); { RED-Book-Format }
CtlBlk[0] := 11; { Read VTOC-Entry }
CtlBlk[1] := i; { track-no }
CD_IoCtl( IoCtlRead, 6);
move( CtlBlk[1], Tracks[i], 6);
{ Tracks[i].Start := Red2Hsg(Tracks[i]); }
end;
With VTOC do
begin
DiskName := '';
UAN_Code := '';
TrackCnt := CD.HiAuTr;
for i := CD.LoAuTr to CD.HiAuTr do
With Titles[i] do
begin
L := LongInt((Tracks[i+1].Start shr 16) and $FF) * 60
+ (Tracks[i+1].Start shr 8) and $FF
- ( LongInt((Tracks[i].Start shr 16) and $FF) * 60
+ (Tracks[i].Start shr 8) and $FF);
Title := '???';
RunMin := L div 60;
RunSec := l - RunMin*60;
Start := Red2Hsg(Tracks[i]);
end
end;
end;
Function CD_Stop: Boolean;
begin { CD StopAudio }
FillChar(CtlBlk, sizeof(CtlBlk), 0);
CtlBlk[0] := 5; { laenge des req-hdr }
CtlBlk[1] := 0; { sub-unit }
CtlBlk[2] := $85; { Kommando }
CtlBlk[3] := 0; { Status-WORT }
CtlBlk[4] := 0;
CtlBlk[5] := 0;
ASM
mov ax, $1510
push ds
pop es
xor cx, cx
mov cl, CD.DrvNo
mov bx, offset CtlBlk
Int $2f
end;
CD.Status := CtlBlk[3] or CtlBlk[4] shl 8;
CD_Stop := CD.Status and $8000 = 0;
end;
Function CD_Resume:Boolean;
begin { ResumeAudio}
CtlBlk[0] := 3; { laenge des req-hdr }
CtlBlk[1] := 0; { sub-unit }
CtlBlk[2] := $88; { Kommando }
CtlBlk[3] := 0; { Status-WORT }
CtlBlk[4] := 0;
Asm
mov ax, Seg @DATA
mov es, ax
mov ax, DevDrvReq
lea bx, CtlBlk
Int 2fh
end;
CD.Status := CtlBlk[3] or CtlBlk[4] shl 8;
CD_Resume := CD.Status and $8000 = 0;
end;
Function CD_GetVol:Boolean;
begin
CtlBlk[0] := 4; { die Lautstaerke lesen }
CD_GetVol := CD_IOCtl(IoCtlRead, 8);
if ((R.Flags and FCARRY) = 0)
then move(CtlBlk[1], CD.VolInfo, 8)
else FillChar( CD.VolInfo, 8, 0)
end;
Function CD_SetVol:Boolean;
begin
CtlBlk[0] := 3; { die Lautstaerke setzen }
CD_SetVol := CD_IOCtl( IoCtlWrite, 8);
end;
Function CD_HeadAdr: Boolean;
Var L:longint; S:String;
begin
FillChar(CtlBlk, sizeof(CtlBlk), 0);
CtlBlk[0] := 1;
CtlBlk[1] := 1; { die Kopfposition im RED-Format }
CD_HeadAdr:= CD_IOCtl(IoCtlRead, 128);
if ((R.Flags and FCARRY) = 0)
then begin
move(CtlBlk[2], L, 4);
if CtlBlk[1] = 1 then
begin
STR( CtlBlk[4]:2, S); CD_REDPos := S;
STR( CtlBlk[3]:2, S); CD_REDPos := CD_REDPos+ ':'+ S;
CD.Sector := Longint(CtlBlk[4]) *4500 +
Longint(CtlBlk[3]) *75 +
Longint(CtlBlk[2])
- 150;
end else
begin
CD.Sector := L;
STR(L:0,CD_HSGPos);
end
end
else FillChar( CD.Sector, 4, 0);
end;
Function CD_Position:Boolean;
var l : longint;
begin
CtlBlk[0] := 12; { Audio-Infos }
CD_Position :=CD_IOCtl(IoCtlRead,10);
Move(CtlBlk[1], CD.CntAdr, 10);
end;
Procedure CD_GetUAN;
begin
CtlBlk[0] := 14; { EAN-Nummer }
If CD_IOCtl(IoCtlRead,10)
then move(CtlBlk[1], CD.Uctrl, 10);
end;
Function CD_MediaChanged:Boolean;
begin
CtlBlk[0] := 9; { Media-Change }
If CD_IOCtl(IoCtlRead, 1)
then move(CtlBlk[1], CD.MedChg, 1 );
CD_MediaChanged:= CD.MedChg <> 1
end;
Procedure CD_Info;
begin
{ CD_Reset; }
If CD_HeadAdr then;
CtlBlk[0] := 6; { Device-parameter }
If CD_IOCtl(IoCtlRead, 4)
then move(CtlBlk[1], CD.DevPar, 4 );
CtlBlk[0] := 7; { Sector-Groesse }
If CD_IOCtl(IoCtlRead, 3) { & Modus }
then move(CtlBlk[1], CD.RawMode, 3 );
CtlBlk[0] := 8; { Volume-Groesse }
If CD_IOCtl(IoCtlRead, 4)
then move(CtlBlk[1], CD.VolSize, 4 );
CtlBlk[0] := 12; { Audio-Infos }
If CD_IOCtl(IoCtlRead,10)
then move(CtlBlk[1], CD.CntAdr, 10);
CtlBlk[0] := 11; { Track-Infos }
CtlBlk[1] := CtlBlk[2]; { aktueller... }
If CD_IOCtl(IoCtlRead, 6)
then move(CtlBlk[1], CD.TrkNo, 6 );
CD_VTOC;
end;
{========= minimale Initialisierung =============}
begin
CD_Avail := CD_Init;
if CD_Avail then CD_INFO
end.